package olegroshka.src.com.bofa.olegroshka.datasource;

import java.util.Iterator;

import olegroshka.src.com.bofa.olegroshka.aggregators.Aggregator;

public class ReportDataSource implements DataSource<Object[]> {
	
	@SuppressWarnings("rawtypes")
	private static final Aggregator[] EMPTY_AGGREGATORS = new Aggregator[]{};
	private static final Object[] EMPTY_DATA = new Object[]{};
	
	private final DataSource<Object[]> dataSource;
	@SuppressWarnings("rawtypes")
	private final Aggregator[] aggregators;
	private final Object[] headerData;
	private final Object[] totals;
	
	@SuppressWarnings("rawtypes")
	public ReportDataSource(
			Object[] headerData,
			DataSource<Object[]> dataSource,
			Aggregator[] aggregators) {
		this.headerData = headerData;
		this.dataSource = dataSource;
		this.aggregators = aggregators;
		this.totals = new Object[aggregators.length];
	}
	
	@SuppressWarnings("rawtypes")
	public ReportDataSource(
			DataSource<Object[]> dataSource,
			Aggregator[] aggregators) {
		this(EMPTY_DATA, dataSource, aggregators);
	}
	
	public ReportDataSource(
			DataSource<Object[]> dataSource) {
		this(EMPTY_DATA, dataSource, EMPTY_AGGREGATORS);
	}

	public Object[] getHeaderData() {
		return headerData;
	}

	public Iterator<Object[]> iterator() {
		return new Iterator<Object[]>() {
			private final Iterator<Object[]> iterator = 
					dataSource.iterator();
			
			public boolean hasNext() {
				return iterator.hasNext();
			}

			@SuppressWarnings({ "unchecked", "rawtypes" })
			public Object[] next() {
				Object[] record = iterator.next();
				for (int i = 0; i < aggregators.length; i++) {
					Aggregator aggregator = aggregators[i];
					if( aggregator != null ) {
						totals[i] = aggregator.aggregate(totals[i], record[i]);
					}
				}
				return record;
			}

			public void remove() {
				throw new UnsupportedOperationException();
			}
		};
	}

	public Object[] getTotals() {
		return totals;
	}

	public void begin() {
		dataSource.begin();
	}

	public void end() {
		dataSource.end();
	}

}
